Cloud Spanner をエミュレーターを使いローカルテスト環境を構築してみた (Java)
西田@CX事業部です
今回は Cloud Spanner をローカル実行するエミュレーターを使い、そのエミュレーターに Java から接続し、ローカルテストを行う環境を構築してみました
基本的に以下のページを元にこの記事は執筆しています
大枠の流れ
- Docker もしくは、 gcloud コマンドでローカル開発環境に Spanner のエミュレーターを起動
- gcloud にエミュレーターを使用するための設定を追加し、エミュレーターに instance を追加
SPANNER_EMULATOR_HOST
環境変数をテスト実行してるプロセスに設定しローカル起動しているエミュレーターに接続
Spannerのエミュレーターを起動
Spanner のエミュレーターを起動する方法は以下の2通りの方法があります
- gcloud コマンドで起動する
- Docker で起動する
※ どちらの方法でも Docker は必要なので、あらかじめインストールしておく必要があります
今回はgloudコマンドで起動する方法でエミュレーターを起動します
gcloud emulators spanner start
上記コマンドで、 gRPC用がlocalhost:9010
で、REST用が localhost:9020
で起動します
エミュレーターをシャットダウンすると、データも削除されます
gcloud にエミュレーター用の Configuration を作成
gcloudコマンドからSpannerのエミュレーターに接続するには以下の設定をする必要があります
- 認証の無効化
- Spanner の endpoint を変更
これらの設定を毎回変えるのは大変なので、 gcloudのConiguration(構成) を作成しておきます
# configurationsを作成 gcloud config configurations create emulator # 任意の名前 # configurationsを切り替え gcloud config configurations active emulator
次にエミュレーターに接続するための設定をします
# 認証を無効化 gcloud config set auth/disable_credentials true # gcloudコマンドのSpannerのEndpointをエミュレーターのREST用 Endpoint に変更 gcloud config set api_endpoint_overrides/spanner http://localhost:9020/
※ エミュレーターに接続する場合でも Project の設定は必要なのにご注意ください。
テスト用の Spanner Instance を作成
テストに使用する、Spanner の Instance を作成します インスタンスにつけた名称は、後ほどJavaから接続するときに使用します(以下の例の test-instance に当たる部分)
gcloud spanner instances create test-instance \ --config=emulator-config --description="Test Instance" --nodes=1
Javaからエミュレーターに接続する
SPANNER_EMULATOR_HOST 環境変数を設定する
Java で利用する Spanner SDKが接続するEndpointを変更するために、 SPANNER_EMULATOR_HOST
環境変数を設定します
直接 JUnit 等を実行するプロセスに対して環境変数を設定しても良いのですが、汎用的に起動できるようにしたかったため、 Javaからコードで環境変数を設定しました
Map<String, String> env = System.getenv(); Class<?> cl = env.getClass(); Field field = cl.getDeclaredField("m"); field.setAccessible(true); Map<String, String> writableEnv = (Map<String, String>) field.get(env); writableEnv.put("SPANNER_EMULATOR_HOST", "localhost:9010");
上記のコードを JUnit の @Before
などに設定して使用します
Spannerのデータベースを作成する
glcoud コマンドで作成した Spanner のインスタンスにデータベースを作成します
まず、DatabaseAdminClient を生成し
SpannerOptions options = SpannerOptions.newBuilder().build(); Spanner spanner = options.getService(); DatabaseAdminClient adminClient = spanner.getDatabaseAdminClient();
データベースを作成します。
データベース作成時に使用するテーブルを作成するDDLを一緒に実行できるので、合わせてテーブルも作成します
final String CREATE_TABLE_SQL = "CREATE TABLE Dog (id INT64 NOT NULL, name STRING(255)) PRIMARY KEY(id)"; OperationFuture<Database, CreateDatabaseMetadata> op = adminClient.createDatabase( "test-instance", // gcloud コマンドで指定したインスタンス名 "test-db", // データベース作成時に流すDDL Arrays.asList( CREATE_TABLE_SQL ) );
作成したデータベースにデータを投入します
以下は作成した Spanner にデータベースに Mutation を使ってデータを投入する例です
final List<Dog> dogs = Arrays.asList( new Dog(1, "しば犬"), new Dog(2, "ブルドック") ); List<Mutation> mutations = new ArrayList<>(); for (Dog sample : dogs) { mutations.add( Mutation.newInsertBuilder("Dog") .set("id").to(dog.id) .set("name").to(dog.name) .build() ); } Spanner spanner = SpannerOptions.newBuilder().build().getService(); SpannerOptions options = SpannerOptions.newBuilder().build(); DatabaseId dbId = DatabaseId.of(options.getProjectId(), "test-instance", "test-db"); DatabaseClient dbClient = spanner.getDatabaseClient(dbId); dbClient.write(mutations);
最後に
Spannerは公式にエミュレーターが用意されているので、簡単にローカルテスト環境を構築することができました。 自動テストを実行するのに、開発者の人数分 Spanenr のインスタンスを用意するのは現実的ではないので、こちらを利用して自動テストができると、開発が捗りそうです